﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using MoqContrib.AutoMock.CommonServiceLocator;
using Moq;

namespace MoqContrib.AutoMock.CommonService.Tests.ClassAnalyzerTests
{
	[TestFixture]
	public class WhenClassHasOneConstructor
	{
		#region Types used for testing
		public class WithDefault
		{
			public WithDefault() { }
		}
		public class WithString
		{
			public WithString(string s) { Dep = s; }
			public string Dep { get; set; }
		}
		public class WithSingleDependency
		{
			public WithSingleDependency(WithDefault dep)
			{
				Dep = dep;
			}
			public WithDefault Dep { get; set; }
		}
		internal interface IService {}
		internal class WithNonVisibleDependency
		{
			public WithNonVisibleDependency(IService service) { }
		}
		public class CtorThrows
		{
			public CtorThrows()
			{
				throw new InvalidCastException();
			}
		}
		#endregion

		private ClassAnalyzer sut;

		[SetUp]
		public void Given()
		{
			sut = new ClassAnalyzer();
			sut.Helper = new CommonServiceLocator.AutoMockHelper();
		}

		[Test]
		public void I_can_construct_a_default_ctor()
		{
			var result = sut.Construct<WithDefault>();
			Assert.That(result, Is.Not.Null);
		}

		[Test]
		public void I_throw_when_constructing_string_ctor()
		{
			Assert.Throws<ArgumentException>(
				() => sut.Construct<WithString>());
		}

		[Test]
		public void I_can_construct_with_mockable_dep_ctor()
		{
			var result = sut.Construct<WithSingleDependency>();
			Assert.That(result, Is.Not.Null);
			Assert.That(result.Dep, Is.Not.Null);
			Assert.That(MockingUtilities.GetMockFor(result.Dep), Is.Not.Null);
		}

		[Test]
		public void I_throw_when_constructing_nonpublic_services()
		{
			Assert.Throws<ArgumentException>(
				() => sut.Construct<WithNonVisibleDependency>());
		}

		[Test]
		public void I_rethrow_when_constructor_throws()
		{
			Assert.Throws<ApplicationException>(
				() => sut.Construct<CtorThrows>());
		}
	}
}
